package org.kalai.unifypay.huanpay;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.TreeMap;

import org.apache.log4j.Logger;
import org.kalai.unifypay.Constant;
import org.kalai.unifypay.util.CipherUtils;
import org.kalai.unifypay.util.CommonUtil;
import org.kalai.unifypay.util.DateUtil;
import org.kalai.unifypay.util.HttpUtil;

import com.alibaba.fastjson.JSON;

public final class HuanPay {
	private static final Logger logger = Logger.getLogger(HuanPay.class);

	/**
	 * 微信主扫支付
	 * @param tranxSN 订单号
	 * @param autoCode 授权码
	 * @param returnUrl 页面通知地址
	 * @param notifyUrl 异步通知地址
	 * @param transAmt 交易金额(分)
	 * @param commodityName 商品名称
	 * @return
	 */
	public static Map<String, Object> authPay(String tranxSN, String autoCode, String notifyUrl, long transAmt, String commodityName){
		String merNo = "800330048161493";
		Date date = new Date();
		Map<String, Object> respMap = CommonUtil.createRespMap("XXXX", "验签失败");
		TreeMap<String, Object> params = new TreeMap<String, Object>();
		params.put("requestNo", DateUtil.format(date, "yyyyMMddHHmmssSSSS"));
		params.put("version", "V1.0");
		params.put("productId", "0113");
		params.put("transId", "17");
		params.put("merNo", merNo);
		params.put("orderDate", DateUtil.format(date, "yyyyMMdd"));
		params.put("orderNo", tranxSN);
		params.put("clientIp", "115.231.102.206");
		params.put("autoCode", autoCode);
		params.put("returnUrl", "null");
		params.put("notifyUrl", notifyUrl);
		params.put("transAmt", transAmt);
		params.put("commodityName", commodityName);
		String signature = HuanHelper.sign(params, merNo);
		params.put("signature", signature);
		logger.info("发送微信主扫交易请求："+tranxSN);
		String ret = HttpUtil.sendHttpsPost(Constant.HUANPAY_URL, params);
		logger.info("接收微信主扫交易请求："+tranxSN);
		if(HuanHelper.design(ret, merNo)){
			Map<String, String> map = HuanHelper.getMap(ret);
            String respCode = map.get("respCode");
            String respMsg = map.get("respDesc");
            if (!"0000".equals(respCode)) {
				logger.info(String.format("微信主扫支付失败[%s][%s-%s]", tranxSN, respCode, respMsg));
			}
            respMap = CommonUtil.createRespMap(respCode.equals("0000") ? "00" : respCode, respMsg);
		}
		return respMap;
	}
	
	/**
	 * 微信被扫支付
	 * @param tranxSN 订单号
	 * @param returnUrl 页面通知地址
	 * @param notifyUrl 异步通知地址
	 * @param transAmt 交易金额
	 * @param commodityName 商品名称
	 * @return codeUrl 支付链接地址
	 */
	public static Map<String, Object> codePay(String tranxSN, String notifyUrl, long transAmt, String commodityName){
		String merNo = "800330048161493";
		Date date = new Date();
		Map<String, Object> respMap = CommonUtil.createRespMap("XXXX", "验签失败");
		TreeMap<String, Object> params = new TreeMap<String, Object>();
		params.put("requestNo", DateUtil.format(date, "yyyyMMddHHmmssSSSS"));
		params.put("version", "V1.0");
		params.put("productId", "0108");
		params.put("transId", "10");
		params.put("merNo", "800330048161493");
		params.put("orderDate", DateUtil.format(date, "yyyyMMdd"));
		params.put("orderNo", tranxSN);
		params.put("clientIp", "115.231.102.206");
		params.put("returnUrl", "null");
		params.put("notifyUrl", notifyUrl);
		params.put("transAmt", transAmt);
		params.put("commodityName", commodityName);
		String signature = HuanHelper.sign(params, merNo);
		params.put("signature", signature);
		logger.info("发送微信被扫交易请求："+tranxSN);
		String ret = HttpUtil.sendHttpsPost(Constant.HUANPAY_URL, params);
		logger.info("接收微信被扫交易请求："+tranxSN);
		if(HuanHelper.design(ret, merNo)){
			Map<String, String> map = HuanHelper.getMap(ret);
            String respCode = map.get("respCode");
            String respMsg = map.get("respDesc");
            respMap = CommonUtil.createRespMap(respCode.equals("0000") ? "00" : respCode, respMsg);
            if (respCode.equals("0000")) {
            		respMap.put("respDesc", "待支付");
            		respMap.put("codeUrl", new String(CipherUtils.decryptBase64(map.get("codeUrl"))));
					respMap.put("imgUrl", map.get("imgUrl"));
            } else {
				logger.info(String.format("微信被扫支付失败[%s-%s]", respCode, respMsg));
			}
		}
		return respMap;
	}
	
	/**
	 * 无卡消费
	 * @param tranxSN 订单号
	 * @param returnUrl 页面通知地址
	 * @param notifyUrl 异步通知地址
	 * @param transAmt 交易金额
	 * @param commodityName 商品名称
	 * @param phoneNo 预留手机号
	 * @param customerName 持卡人姓名
	 * @param cerdId 身份证号
	 * @param acctNo 卡号
	 * @param cvn2 CVN2
	 * @param expDate 卡有效期
	 */
	public static Map<String, Object> noCardPay(String tranxSN, String notifyUrl, long transAmt, String commodityName, String phoneNo,
			String customerName, String cerdId, String acctNo, String cvn2, String expDate){
		String merNo = "800330048161494";
		Date date = new Date();
		Map<String, Object> respMap = CommonUtil.createRespMap("XXXX", "验签失败");
		TreeMap<String, Object> params = new TreeMap<String, Object>();
		params.put("requestNo", DateUtil.format(date, "yyyyMMddHHmmssSSSS"));
		params.put("version", "V1.0");
		params.put("productId", "0103");
		params.put("transId", "01");
		params.put("merNo", merNo);
		params.put("orderDate", DateUtil.format(date, "yyyyMMdd"));
		params.put("orderNo", tranxSN);
		params.put("returnUrl", "null");
		params.put("notifyUrl", notifyUrl);
		params.put("transAmt", transAmt);
		params.put("commodityName", commodityName);
		params.put("phoneNo", phoneNo);
		params.put("customerName", customerName);
		params.put("cerdType", "01");
		params.put("cerdId", cerdId);
		params.put("acctNo", acctNo);
		params.put("cvn2", cvn2);
		params.put("expDate", expDate);
		String signature = HuanHelper.sign(params, merNo);
		params.put("signature", signature);
		logger.info("发送无卡消费交易请求："+tranxSN);
		String ret = HttpUtil.sendHttpsPost(Constant.HUANPAY_URL, params);
		logger.info("接收无卡消费交易请求："+tranxSN);
		if(HuanHelper.design(ret, merNo)){
			Map<String, String> map = HuanHelper.getMap(ret);
            String respCode = map.get("respCode");
            String respMsg = map.get("respDesc");
            if (!"0000".equals(respCode)) {
				logger.info(String.format("无卡消费失败[%s-%s]", respCode, respMsg));
			}
            respMap = CommonUtil.createRespMap(respCode.equals("0000") ? "00" : respCode, respMsg);
		}
		return respMap;
	}
	
	/**
	 * 余额代付
	 * @param tranxSN 订单号
	 * @param notifyUrl 异步通知地址
	 * @param transAmt 代付金额
	 * @param phoneNo 代付银行手机号
	 * @param customerName 代付账户名
	 * @param cerdId 代付身份证号
	 * @param accBankNo 代付开户行号
	 * @param accBankName 代付开户行名称
	 * @param acctNo 代付账号
	 * @return
	 */
	public static Map<String, String> proxyPay(String tranxSN, String notifyUrl, long transAmt, String phoneNo, String customerName, String cerdId, String accBankNo, 
			String accBankName, String acctNo, boolean isD0, boolean isWx){
		String merNo = "80033004816149" + (isWx ? "3" : "2");
		Date date = new Date();
		TreeMap<String, Object> params = new TreeMap<String, Object>();
		params.put("requestNo", DateUtil.format(date, "yyyyMMddHHmmssSSSS"));
		params.put("version", "V1.0");
		params.put("productId", isD0 ? "0203" : "0201");// 0201-非垫支,0203-垫支(T0)
		params.put("transId", "07");
		params.put("merNo", merNo);
		params.put("orderDate", DateUtil.format(date, "yyyyMMdd"));
		params.put("orderNo", tranxSN);
		params.put("notifyUrl", notifyUrl);
		params.put("transAmt", transAmt);
		params.put("isCompay", "0");
		params.put("phoneNo", phoneNo);
		params.put("customerName", customerName);
		params.put("cerdType", "01");
		params.put("cerdId", cerdId);
		params.put("accBankNo", accBankNo);
		params.put("accBankName", accBankName);
		params.put("acctNo", acctNo);
		String signature = HuanHelper.sign(params, merNo);
		params.put("signature", signature);
		logger.info("发送余额代付交易请求："+tranxSN);
		String ret = HttpUtil.sendHttpsPost(Constant.HUANPAY_URL, params);
		if(HuanHelper.design(ret, merNo)){
			Map<String, String> retMap = HuanHelper.getMap(ret);
			logger.info("接收余额代付交易请求："+tranxSN+"-"+retMap);
			return HuanHelper.getMap(ret);
//            if(respCode.equals("P000") || respCode.equals("0000")){
//            	return true;
//            } else {
//            	logger.error(String.format("余额代付失败[%s-%s]", respCode, respMsg));
//			}
		}
		return null;
	}
	
	/**
	 * 公众号支付
	 * @param tranxSN
	 * @param wxOpenid
	 * @param notifyUrl
	 * @param transAmt
	 * @param commodityName
	 * @return
	 */
	public static Map<String, Object> wxGzPay(String tranxSN, String wxOpenid, String returnUrl, String notifyUrl, long transAmt, String commodityName){
		String merNo = "800330048161493";
		Date date = new Date();
		Map<String, Object> respMap = CommonUtil.createRespMap("XXXX", "验签失败");
		TreeMap<String, Object> params = new TreeMap<String, Object>();
		params.put("requestNo", DateUtil.format(date, "yyyyMMddHHmmssSSSS"));
		params.put("version", "V1.0");
		params.put("productId", "0112");
		params.put("transId", "16");
		params.put("merNo", "800330048161493");
		params.put("orderDate", DateUtil.format(date, "yyyyMMdd"));
		params.put("orderNo", tranxSN);
		params.put("openid", wxOpenid);
		params.put("clientIp", "115.231.102.206");
		params.put("returnUrl", returnUrl);
		params.put("notifyUrl", notifyUrl);
		params.put("transAmt", transAmt);
		params.put("commodityName", commodityName);
		String signature = HuanHelper.sign(params, merNo);
		params.put("signature", signature);
		logger.info("发送公众号支付交易请求："+tranxSN);
		String ret = HttpUtil.sendHttpsPost(Constant.HUANPAY_URL, params);
		logger.info("接收公众号支付交易请求："+tranxSN);
		if(HuanHelper.design(ret, merNo)){
			Map<String, String> map = HuanHelper.getMap(ret);
            String respCode = map.get("respCode");
            String respMsg = map.get("respDesc");
            respMap = CommonUtil.createRespMap(respCode.equals("0000") ? "00" : respCode, respMsg);
            if (respCode.equals("0000")) {
            	respMap.put("respDesc", "支付中");
            	respMap.put("codeUrl", new String(CipherUtils.decryptBase64(map.get("payInfo"))));
            } else {
				logger.info(String.format("微信公众号支付失败[%s-%s]", respCode, respMsg));
			}
		}
		return respMap;
	}
	
	/**
	 * 微信APP支付  暂无交易权限
	 * @param tranxSN 订单号
	 * @param returnUrl 页面通知地址
	 * @param notifyUrl 异步通知地址
	 * @param transAmt 交易金额
	 * @param commodityName 商品名称
	 * @return tokenId 授权码
	 */
	@Deprecated
	public static String wxAppPay(String tranxSN, String returnUrl, String notifyUrl, long transAmt, String commodityName){
		Date date = new Date();
		Map<String, Object> respMap = CommonUtil.createRespMap("XXXX", "验签失败");
		TreeMap<String, Object> params = new TreeMap<String, Object>();
		params.put("requestNo", DateUtil.format(date, "yyyyMMddHHmmssSSSS"));
		params.put("version", "V1.0");
		params.put("productId", "0108");
		params.put("transId", "11");
		params.put("merNo", "800330048161493");
		params.put("orderDate", new SimpleDateFormat("yyyyMMdd").format(date));
		params.put("orderNo", tranxSN);
		params.put("returnUrl", returnUrl);
		params.put("notifyUrl", notifyUrl);
		params.put("transAmt", transAmt);
		params.put("commodityName", commodityName);
		String signature = HuanHelper.sign(params, "1493");
		params.put("signature", signature);
		String ret = HttpUtil.sendHttpsPost(Constant.HUANPAY_URL, params);
		if(HuanHelper.design(ret, "1493")){
			Map<String, String> map = HuanHelper.getMap(ret);
            String respCode = map.get("respCode");
            String respMsg = map.get("respDesc");
            respMap = CommonUtil.createRespMap(respCode, respMsg);
            if(respCode.equals("0000")){
            	respMap.put("tokenId", new String(CipherUtils.decryptBase64(map.get("tokenId"))));
            }
		}
		return JSON.toJSONString(respMap);
	}
	
	/**
	 * 微信WAP支付
	 * @param tranxSN 订单号
	 * @param returnUrl 页面通知地址
	 * @param notifyUrl 异步通知地址
	 * @param transAmt 交易金额
	 * @param commodityName 商品名称
	 * @return payInfo 支付地址
//	 */
	@Deprecated
	public static String wxWapPay(String tranxSN, String returnUrl, String notifyUrl, long transAmt, String commodityName){
		Date date = new Date();
		Map<String, Object> respMap = CommonUtil.createRespMap("XXXX", "验签失败");
		TreeMap<String, Object> params = new TreeMap<String, Object>();
		params.put("requestNo", new SimpleDateFormat("yyyyMMddHHmmssSSSS").format(date));
		params.put("version", "V1.0");
		params.put("productId", "0108");
		params.put("transId", "12");
		params.put("merNo", "800330048161493");
		params.put("orderDate", new SimpleDateFormat("yyyyMMdd").format(date));
		params.put("orderNo", tranxSN); 
		params.put("returnUrl", returnUrl);
		params.put("notifyUrl", notifyUrl);
		params.put("transAmt", transAmt);
		params.put("commodityName", commodityName);
		String signature = HuanHelper.sign(params, "800330048161493");
		params.put("signature", signature);
		String ret = HttpUtil.sendHttpsPost(Constant.HUANPAY_URL, params);
		if(HuanHelper.design(ret, "800330048161493")){
			Map<String, String> map = HuanHelper.getMap(ret);
            String respCode = map.get("respCode");
            String respMsg = map.get("respDesc");
            respMap = CommonUtil.createRespMap(respCode, respMsg);
            if(respCode.equals("0000")){
            	respMap.put("payInfo", new String(CipherUtils.decryptBase64(map.get("payInfo"))));
            }
		}
		return JSON.toJSONString(respMap);
	}

	/**
	 * 退货交易
	 * @param tranxSN 订单号
	 * @param orderDate 原订单交易日期  yyyyMMdd
	 * @param orderTranxSN 原交易订单号
	 * @param returnUrl 页面通知地址
	 * @param notifyUrl 异步通知地址
	 * @param transAmt 订单交易金额
	 * @param refundReson 退货原因
	 * @return orderTime 订单交易时间
	 */
	@Deprecated
	public static String refund(String tranxSN, String orderDate, String orderTranxSN, String returnUrl, String notifyUrl, long transAmt, String refundReson){
		String merNo = "800330048161493";
		Date date = new Date();
		Map<String, Object> respMap = CommonUtil.createRespMap("XXXX", "验签失败");
		TreeMap<String, Object> params = new TreeMap<String, Object>();
		params.put("requestNo", new SimpleDateFormat("yyyyMMddHHmmssSSSS").format(date));
		params.put("version", "V1.0");
		params.put("transId", "02");
		params.put("merNo", merNo);
		params.put("orderDate", new SimpleDateFormat("yyyyMMdd").format(date));
		params.put("orderNo", tranxSN);
		params.put("origOrderDate", orderDate);
		params.put("origOrderNo", orderTranxSN);
		params.put("returnUrl", returnUrl);
		params.put("notifyUrl", notifyUrl);
		params.put("transAmt", transAmt);
		params.put("refundReson", refundReson);
		String signature = HuanHelper.sign(params, merNo);
		params.put("signature", signature);
		String ret = HttpUtil.sendHttpsPost(Constant.HUANPAY_URL, params);
		if(HuanHelper.design(ret, merNo)){
			Map<String, String> map = HuanHelper.getMap(ret);
            String respCode = map.get("respCode");
            String respMsg = map.get("respDesc");
            respMap = CommonUtil.createRespMap(respCode, respMsg);
            if(respCode.equals("0000")){
            	respMap.put("orderTime", new String(CipherUtils.decryptBase64(map.get("orderTime"))));
            }
		}
		return JSON.toJSONString(respMap);
	}

	/**
	 * 撤销交易
	 * @param tranxSN 订单号
	 * @param orderTranxSN 原交易订单号
	 * @param returnUrl 页面通知地址
	 * @param notifyUrl 异步通知地址
	 * @param transAmt 订单交易金额
	 * @return orderTime 订单交易时间
	 */
	@Deprecated
	public static String revoke(String tranxSN, String orderTranxSN, String returnUrl, String notifyUrl, long transAmt){
		String merNo = "800330048161493";
		Date date = new Date();
		Map<String, Object> respMap = CommonUtil.createRespMap("XXXX", "验签失败");
		TreeMap<String, Object> params = new TreeMap<String, Object>();
		params.put("requestNo", new SimpleDateFormat("yyyyMMddHHmmssSSSS").format(date));
		params.put("version", "V1.0");
		params.put("transId", "03");
		params.put("merNo", merNo);
		params.put("orderDate", new SimpleDateFormat("yyyyMMdd").format(date));
		params.put("orderNo", tranxSN);
		params.put("origOrderNo", orderTranxSN);
		params.put("returnUrl", returnUrl);
		params.put("notifyUrl", notifyUrl);
		params.put("transAmt", transAmt);
		String signature = HuanHelper.sign(params, merNo);
		params.put("signature", signature);
		String ret = HttpUtil.sendHttpsPost(Constant.HUANPAY_URL, params);
		if(HuanHelper.design(ret, merNo)){
			Map<String, String> map = HuanHelper.getMap(ret);
            String respCode = map.get("respCode");
            String respMsg = map.get("respDesc");
            respMap = CommonUtil.createRespMap(respCode, respMsg);
            if(respCode.equals("0000")){
            	respMap.put("orderTime", new String(CipherUtils.decryptBase64(map.get("orderTime"))));
            }
		}
		return JSON.toJSONString(respMap);
	}
	
	/**
	 * 手机银联APP支付
	 * @param tranxSN 订单号
	 * @param acctNo 交易卡号  为空串时自由选择  上传时不可选择
	 * @param notifyUrl 异步通知地址
	 * @param transAmt 交易金额
	 * @param commodityName 商品名称
	 * @return tokenId 启动控件的流水号
	 */
	public static String unionAppPay(String tranxSN, String acctNo, String notifyUrl, long transAmt, String commodityName){
		String merNo = "800330048161506";
		Date date = new Date();
		Map<String, Object> respMap = CommonUtil.createRespMap("XXXX", "验签失败");
		TreeMap<String, Object> params = new TreeMap<String, Object>();
		params.put("requestNo", new SimpleDateFormat("yyyyMMddHHmmssSSSS").format(date));
		params.put("version", "V1.0");
		params.put("productId", "0110");
		params.put("transId", "01");
		params.put("merNo", merNo);
		params.put("orderDate", new SimpleDateFormat("yyyyMMdd").format(date));
		params.put("orderNo", tranxSN);
		params.put("acctNo", acctNo);
		params.put("notifyUrl", notifyUrl);
		params.put("transAmt", transAmt);
		params.put("commodityName", commodityName);
		String signature = HuanHelper.sign(params, merNo);
		params.put("signature", signature);
		String ret = HttpUtil.sendHttpsPost(Constant.HUANPAY_URL, params);
		if(HuanHelper.design(ret, merNo)){
			Map<String, String> map = HuanHelper.getMap(ret);
            String respCode = map.get("respCode");
            String respMsg = map.get("respDesc");
            respMap = CommonUtil.createRespMap(respCode, respMsg);
            if(respCode.equals("0000")){
            	respMap.put("tokenId", new String(CipherUtils.decryptBase64(map.get("tokenId"))));
            }
		}
		return JSON.toJSONString(respMap);
	}
	
	/**
	 * 手机银联WAP支付
	 * @param tranxSN 订单号
	 * @param acctNo 交易卡号  为空串时自由选择  上传时不可选择
	 * @param returnUrl 前台跳转地址
	 * @param notifyUrl 异步通知地址
	 * @param transAmt 交易金额
	 * @param commodityName 商品名称
	 * @return tokenId 启动控件的流水号
	 * @return formfield 前台H5页面表单字段
	 * @return formaction 前台H5表单提交地址
	 */
	public static String unionWebPay(String tranxSN, String acctNo, String returnUrl, String notifyUrl, long transAmt, String commodityName){
		String merNo = "800330048161506";
		Date date = new Date();
		Map<String, Object> respMap = CommonUtil.createRespMap("XXXX", "验签失败");
		TreeMap<String, Object> params = new TreeMap<String, Object>();
		params.put("requestNo", new SimpleDateFormat("yyyyMMddHHmmssSSSS").format(date));
		params.put("version", "V1.0");
		params.put("productId", "0111");
		params.put("transId", "01");
		params.put("merNo", merNo);
		params.put("orderDate", new SimpleDateFormat("yyyyMMdd").format(date));
		params.put("orderNo", tranxSN);
		params.put("acctNo", acctNo);
		params.put("returnUrl", returnUrl);
		params.put("notifyUrl", notifyUrl);
		params.put("transAmt", transAmt);
		params.put("commodityName", commodityName);
		String signature = HuanHelper.sign(params, merNo);
		params.put("signature", signature);
		String ret = HttpUtil.sendHttpsPost(Constant.HUANPAY_URL, params);
		if(HuanHelper.design(ret, merNo)){
			Map<String, String> map = HuanHelper.getMap(ret);
            String respCode = map.get("respCode");
            String respMsg = map.get("respDesc");
            respMap = CommonUtil.createRespMap(respCode, respMsg);
            if(respCode.equals("0000")){
            	respMap.put("formfield", new String(CipherUtils.decryptBase64(map.get("formfield"))));
            	respMap.put("formaction", new String(CipherUtils.decryptBase64(map.get("formaction"))));
            	respMap.put("tokenId", new String(CipherUtils.decryptBase64(map.get("tokenId"))));
            }
		}
		return JSON.toJSONString(respMap);
	}
	
	public static void main(String[] args) {//
		//测试微信主扫  测试通过
//		System.out.println(wxScancodePay((Math.random() * 1000000000)+"", "null", "http://renne66.imwork.net:28798/unifypay/WXNotify", 1, "测试交易"));
		//测试微信被扫
//		System.out.println(wxBarcodePay("20160811155430", "130136594026467564", "null", "null", 1, "游泳的圈子叫游泳圈"));
		//测试无卡支付 测试通过
//		System.out.println(noCardPay("20160811165430", "test", "test", 1, "眼镜店", "17097221966", "曾庆达", "420624199209212219", "6225768726230772", "***", "1701"));
		//测试代付  测试通过
//		System.out.println(proxyPay("20160812112234", "http://renne66.imwork.net:28798/unifypay/WXNotify", 20, "17097221966", "蒋哲东", "339005199003198217", "313331040008", "温州银行股份有限公司杭州分行", "6219770117254823", false));
//		System.out.println(wxWapPay("20160813", "", "", 1, "ceshi"));
//		System.out.println(wxGzPay("20160811165441", "2b00f73e533eb06b9ecf1c6d66c37b63", "http://renne66.imwork.net:28798/unifypay/WXNotify", 1, "测试交易"));
		//测试撤销交易 {"respCode":"0018","respMsg":"未授权的交易"}
//		System.out.println(revoke("20160811110430", "20160811110030", "test", "test", 1));
	}
}
